
/**
 * AppleIIGo
 * MIG (Magic Interface Glue) class
 * (C) 2008 by Marc S. Ressl(mressl@umich.edu)
 * Released under the GPL
 */

#include "MIG.h"
#include "InternalSmartPort2IWM.h"
// To-Do: remove debugging
#include <stdio.h>

MIG::MIG(Motherboard * motherboard) : Device(motherboard, "MIG") {
}

void MIG::onDevicesConnected() {
	mmu = motherboard->getMmu();
	timingGenerator = motherboard->getTimingGenerator();
	internalSlot6Device = motherboard->getSlotDevice(SLOT_INTERNAL + 6);
}

void MIG::onMemoryRequested() {
	migMemoryOffset =
		motherboard->getMemory()->requestMemory(MIGMEMORY_BYTENUM);
}

void MIG::onMemoryAllocated() {
	migMemory = motherboard->getMemory()->getMemory(migMemoryOffset);
}

void MIG::onResetAsserted(bool isRestart) {
	migBankOffset = 0;
	
	if (!isRestart)
		return;
	
	for (UINT32 index = 0; index < MIGMEMORY_BYTENUM; index++)
		migMemory[index] = 0;
}

void MIG::writeIo(UINT16 address, UINT8 value) {
	UINT8 diskRegister;
	
	// To-Do: remove debugging
//	printf("MIG W %04x:%02x\n", address, value);
	switch (address & 0xfe0) {
		case 0xc80:
		case 0xcc0:
			diskRegister = internalSlot6Device->readIo(0xc031);
			setBit(diskRegister, DISKREGISTER_DRIVE35, !(address & 0x40));
			internalSlot6Device->writeIo(0xc031, diskRegister);
			printf("MIG operation: W %04x:%02x\n", address, value);
			break;
		case 0xe00:
			migMemory[migBankOffset + (address & 0x1f)] = value;
			break;
		case 0xea0:
			migBankOffset = 0;
			break;
		default:
			printf("Unknown MIG operation: W %04x:%02x\n", address, value);
			break;
	}
}

UINT8 MIG::readIo(UINT16 address) {
	if ((address & 0xff00) != 0xce00)
		return mmu->readMemoryDirect(address);
	
	UINT8 diskRegister;
	
	// To-Do: remove debugging
//	printf("MIG R %04x\n", address);
	switch (address & 0xfe0) {
		case 0xe00:
			return migMemory[migBankOffset + (address & 0x1f)];
		case 0xe20:
			migBankOffset += MIGBANK_BYTENUM;
			migBankOffset &= (MIGMEMORY_BYTENUM - 1);
			break;
		case 0xe40:
		case 0xe60:
			diskRegister = internalSlot6Device->readIo(0xc031);
			setBit(diskRegister, DISKREGISTER_HEAD1, (address & 0x20));
			internalSlot6Device->writeIo(0xc031, diskRegister);
			printf("MIG operation: R %04x\n", address);
			break;
		case 0xea0:
			migBankOffset = 0;
			break;
		default:
			printf("Unknown MIG operation: R %04x\n", address);
			break;
	}
	
	return timingGenerator->readFloatingBus();
}
